package com.hup.utils.io.csv;

import lombok.extern.log4j.Log4j2;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * @author hugan
 * @date 2020/2/21
 */
@Log4j2
public class CsvReader {

    public static <T> CsvData<T> read(String path, CsvRowConverter<T> converter) throws IOException {
        return read(path, converter, StandardCharsets.UTF_8);
    }

    public static <T> CsvData<T> read(String path, CsvRowConverter<T> converter, Charset charset) throws IOException {
        File file = new File(path);
        CSVFormat csvFormat = CSVFormat.POSTGRESQL_CSV;
        try (CSVParser parse = CSVParser.parse(new FileInputStream(file), charset, csvFormat)) {
            CsvData<T> res = new CsvData<>();
            res.fileName = file.getName();

            Iterator<CSVRecord> it = parse.iterator();
            CSVRecord next;
            if (!it.hasNext() || (next = it.next()) == null) {
                throw new IOException("文件内容为空");
            }

            //head
            int headSize = next.size();
            res.heads = new String[headSize];
            for (int i = 0; i < next.size(); i++) {
                res.heads[i] = next.get(i);
            }
            //rows
            res.lstRow = new ArrayList<>();
            int rowIndex = 1;
            while (it.hasNext()) {
                next = it.next();
                int columnSize = next.size();
                if (headSize != columnSize) {
                    log.warn("列数不一致:表头有{}列, 第{}行有{}列", headSize, rowIndex, columnSize);
                }

                ArrayList<String> line = new ArrayList<>(columnSize);
                for (int i = 0; i < columnSize; i++) {
                    line.add(next.get(i));
                }
                T rowData = converter.castFromCsvLine(rowIndex, line);
                res.lstRow.add(rowData);
                rowIndex++;
            }

            return res;
        }
    }

    public interface CsvRowConverter<T> {
        /**
         * @param rowIndex 起始于1
         */
        T castFromCsvLine(int rowIndex, ArrayList<String> line);
    }

    public static class CsvData<T> {
        public String fileName;
        public String[] heads;
        public ArrayList<T> lstRow;

        @Override
        public String toString() {
            return "CsvData{" +
                    "fileName=" + fileName +
                    ", lstRow=" + (lstRow == null ? null : lstRow.size()) +
                    '}';
        }

        public int getRowCount() {
            return lstRow.size();
        }
    }

}
